﻿using ConsoleApp2.Layer;
using ConsoleApp2.util;
using DenseCRF;
using FCN;
using Model;
using System;
using System.Linq;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            //test();
            //  contest();
          //  D4DTEST();
            TEST();


            //var T = 1;
            //var batch_size = 1;//var h = 4; var  w = 8;

            //Matrix[] x = new Matrix[] { new Matrix(1, 1)};
            //x[0].values[0, 0] = 0.5f;
            //Matrix[] y = new Matrix[] { new Matrix(1, 1) };
            //y[0].values[0, 0] = 1f;
            //var dhidden = 1;
            //var max_epoch = 1;

            //var conGRU = new ConvGRUCell(batch_size, dhidden, 1);
            //MSELoss loss_fn = new util.MSELoss();
            //float loss = 0.0f;
            //for (var count = 0; count < max_epoch; count++)
            //{
            //    loss = 0.0f;
            //    Matrix[] state = null;
            //    for (var TI = 0; TI < T; TI++)
            //    {
            //        state = conGRU.forward(x, state);

            //        loss += loss_fn.calcRMSE(state, y);

            //    }

            //}
        }
        static void D4DTEST()
        {
            var T = 5;      // # sequence length

            //string[] Directs = System.IO.Directory.GetDirectories("res");

        
            //#define batch_size, channels, height, width
            var batch_size = 1;//var h = 4; var  w = 8;
          //  var hide = 3;
            Matrix[][] matricesX = new Matrix[T][];//b,c
            Matrix[][] matricesY = new Matrix[T][];//d,c
           


            //   foreach (string dd in Directs)
            //   {
            string[] files = System.IO.Directory.GetFiles("res");
            //    int index = Convert.ToInt32(dd.Split('\\')[1]);

            files = files.OrderBy(p => p).ToArray();
            for (var tt = 0; tt < T; tt++)
            {
                if (matricesX[tt] == null)
                {
                    matricesX[tt] = new Matrix[batch_size];
                    matricesY[tt] = new Matrix[batch_size];
                }
                for (var bb = 0; bb < batch_size; bb++)
                {

                    string file = files[tt + bb];
                    Matrix anno1 = DenseCRF.util.readRADARMatrix(file);
                    anno1.values = ImgUtil.BilinearInterp(anno1.values, anno1.values.GetLength(0)  , anno1.values.GetLength(1) );
                 //   anno1.values = ImgUtil.THEmedian(anno1.values);
                    //ImgUtil.DrawRadar(anno1.values, file+".jpg");
                    matricesX[tt][bb] = ( anno1.Clone());

                    string file1 = files[tt + bb+1 ];
                    Matrix anno2 = DenseCRF.util.readRADARMatrix(file1);
                    anno2.values = ImgUtil.BilinearInterp(anno2.values, anno2.values.GetLength(0) , anno2.values.GetLength(1) );
                 //   anno1.values = ImgUtil.THEmedian(anno1.values);
                    matricesY[tt][bb] = anno2.Clone();
                }
            }


            //  }



            var max_epoch = 10;

            var lr = 0.1f;   // # learning rate

            LstmGRUcell conGRU = null;
            MSELoss loss_fn = new util.MSELoss();
            float loss = 0.0f;
            Matrix[] state = null;
            int countt = 0;

            while (countt <= 6)
            {
                conGRU = new LstmGRUcell(batch_size, batch_size, 5);

                for (var count = 0; count < max_epoch; count++)
                {
                    loss = 0.0f;
                    state = null;
                    Matrix[,] allDgrid = null;
                    for (var TI = 0; TI < T-1; TI++)
                    {
                        state = conGRU.forward(matricesX[TI], state);
                      //  Matrix[][] statett = Matrix.chunk(state, 2);
                        loss += loss_fn.calcRMSE(state, matricesY[TI]);

                        Matrix[,] teemp = conGRU.Backward(state, matricesY[TI]);
                        //if (allDgrid == null)
                        //    allDgrid = teemp;
                        //else
                        //    allDgrid = Matrix.MatrixAdd(allDgrid, teemp);
                        conGRU.update(teemp, lr);
                        //conGRU.Backward(state, matricesY[TI], lr);
                    }
                    Console.WriteLine("loss:" + loss);
                  
                    // Matrix[,] DW = loss_fn.MESBackwrad(matricesX, matricesdata, matricesY, 5, conGRU.input_sizeNUM, conGRU.output_sizenum, conGRU._stride, conGRU._padding);
                    //   float[] Basic = loss_fn.MESBasic(DW, conGRU.output_sizenum);
                }
               
                float[,] temp = ImgUtil.Bilinear(state[0].values, 512, 512);
                ImgUtil.DrawRadar(temp, "test" + countt + ".jpg");
                Console.WriteLine("out:" + "test" + countt + ".jpg");
                countt++;
                for (var TI = 0; TI < T - 1; TI++)
                {
                    matricesX[TI] = matricesX[TI + 1];
                }
             //   Matrix[][] statet = Matrix.chunk(state, 2);
                matricesX[matricesX.Length - 1] = state;

            }
        }
        static void test()
        {
            int szie = 5;
            var conGRU = new convlayer(1, 1, 3, 1, 2);
            conGRU.weights[0, 0].values = new float[,] { { 0.3050f, 0.0340f, -0.2733f }, { 0.3124f, 0.0259f, 0.0960f }, { -0.1159f, 0.1542f, 0.2028f } };
            conGRU.weights[0, 1].values = new float[,] { { 0.3050f, 0.0340f, -0.2733f }, { 0.3124f, 0.0259f, 0.0960f }, { -0.1159f, 0.1542f, 0.2028f } };
            conGRU.basicData = new float[] { -0.2914f, -0.2914f };
            // conGRU.ConvGates.weights
            Matrix[] input = new Matrix[1];
            input[0] = new Matrix(szie, szie);
            Matrix[] output = new Matrix[2];
            output[0] = new Matrix(5, 5);
            output[1] = new Matrix(5, 5);
            for (var i = 0; i < szie; i++)
            {
                for (var j = 0; j < szie; j++)
                {
                    if (i == 3)
                    {
                        input[0].values[i, j] = 0.5f;
                        //input[1].values[i, j] = 0.5f;
                    }
                    else
                        input[0].values[i, j] = 0.0f;

                }

            }
            for (var i = 0; i < 5; i++)
            {
                for (var j = 0; j < 5; j++)
                {

                    output[0].values[i, j] = 1f;
                    output[1].values[i, j] = 1f;
                }
            }
            //input[0, 0].values[2, 2] = 1f;


            for (int i = 0; i < 1; i++)//循环就是加之和
            {
                Matrix[] hi = conGRU.Forward(input);
                //SigmodLayer sl = new SigmodLayer();
                TanhLayer tl = new TanhLayer();
                MulLayer ml = new MulLayer();

                //Matrix[][] TRg = Matrix.chunk(hi, 2);
                hi = tl.forward(hi);
                //   hi = ml.forward(hi, input);
                // hi = sl.forward(hi);
                //hi= Matrix.MatrixAdd(hi, 0.8f);
                MSELoss msloss = new MSELoss();
                DbackDelegate Dback = delegate (int indexx, int x, int y, float xdata, float ydata, float tdata)
                {
                    float bb = -2 * (xdata) * (ydata - tdata);
                    bb = tl.backward(indexx, x, y, bb);
                    //   bb = ml.backward(indexx, x, y, bb);
                    return bb;
                };
                Matrix[] MEStemp2 = msloss.MESBackwradconv(input, hi, output, Dback, 3, 1, 1);


                //  MEStemp2 = ml.backward(MEStemp2);

                //Matrix[] MEStemp = msloss.MESBackwrad(input, hi, output,3,1,1);
                //  MEStemp= ml.backward(MEStemp);
                //   MEStemp = msloss.MESDconv(MEStemp, 3, 1, 1);
                //   Matrix[] lossgrid = msloss.MESBackwrad(input, hi, output, conGRU.Kszie, conGRU.stride, conGRU.padding);
                //lossgrid = tl.backward(lossgrid);
                // lossgrid = ml.backward(lossgrid);
                //  lossgrid=sl.backward(lossgrid);
            }
        }
        static void TEST()
        {
            var T = 10;      // # sequence length

            //string[] Directs = System.IO.Directory.GetDirectories("res");

            var channels = 1;
            //#define batch_size, channels, height, width
            var batch_size = 1;//var h = 4; var  w = 8;
            Matrix[][,] matricesX = new Matrix[T][,];//b,c
            Matrix[][,] matricesY = new Matrix[T][,];//d,c
            var dhidden = 1;       //  # hidden state size


            //   foreach (string dd in Directs)
            //   {
            string[] files = System.IO.Directory.GetFiles("res");
            //    int index = Convert.ToInt32(dd.Split('\\')[1]);

            files = files.OrderBy(p => p).ToArray();
            for (var tt = 0; tt < T; tt++)
            {
                if (matricesX[tt] == null)
                {
                    matricesX[tt] = new Matrix[batch_size, channels];
                    matricesY[tt] = new Matrix[batch_size, dhidden];
                }
                for (var bb = 0; bb < batch_size; bb++)
                {
                   
                      string file = files[tt + bb];
                      Matrix anno1 = DenseCRF.util.readRADARMatrix(file);
                     ImgUtil.DrawRadar(anno1.values, file + ".jpg");
                    //anno1.values = ImgUtil.BilinearInterp(anno1.values, anno1.values.GetLength(0)/2, anno1.values.GetLength(1)/2);
                   
                  //  anno1.values = ImgUtil.THEmedian(anno1.values);
                    matricesX[tt][bb, 0] = anno1.Clone();
                    
                    string file1 = files[tt + bb+1];
                    Matrix anno2 = DenseCRF.util.readRADARMatrix(file1);
                  //  anno2.values = ImgUtil.BilinearInterp(anno2.values, anno2.values.GetLength(0)/2 , anno2.values.GetLength(1)/2);
                   // anno1.values = ImgUtil.THEmedian(anno1.values);
                    matricesY[tt][bb, 0] = anno2.Clone();
                }
            }


            //  }



            var max_epoch = 5;

            var lr = 0.1f;   // # learning rate

            ConvGRUCell conGRU = null;
            MSELoss loss_fn = new util.MSELoss();
            float loss = 0.0f;
            Matrix[,] state = null;
           
                conGRU = new ConvGRUCell(batch_size, dhidden, 5);

                for (var count = 0; count < max_epoch; count++)
                {
                    loss = 0.0f;
                    state = null;
                    Matrix[,] allDgrid = null;
                    for (var TI = 0; TI < T; TI++)
                    {
                        state = conGRU.forward(matricesX[TI], state);

                        loss = loss_fn.calcRMSE(state, matricesY[TI]);

                        Matrix[,] teemp = conGRU.Backward(state, matricesY[TI]);
                        //if (allDgrid == null)
                        //    allDgrid = teemp;
                        //else
                        //    allDgrid = Matrix.MatrixAdd(allDgrid, teemp);
                        Console.WriteLine("loss:" + loss);
                        conGRU.update(teemp, lr);
                        //conGRU.Backward(state, matricesY[TI], lr);
                    }
                 
                    // Matrix[,] DW = loss_fn.MESBackwrad(matricesX, matricesdata, matricesY, 5, conGRU.input_sizeNUM, conGRU.output_sizenum, conGRU._stride, conGRU._padding);
                    //   float[] Basic = loss_fn.MESBasic(DW, conGRU.output_sizenum);
                }

                float[,] temp = ImgUtil.Bilinear(state[0, 0].values, 512, 512);
                //ImgUtil.DrawRadar(temp, "test" + countt + ".jpg");
                //Console.WriteLine("out:" + "test" + countt + ".jpg");
                //countt++;
                //for (var TI = 0; TI < T - 1; TI++)
                //{
                //    matricesX[TI] = matricesX[TI + 1];
                //}
                //matricesX[matricesX.Length - 1] = state;

        
        }
    }
}
